From ceccf38e96b975e625e311489a5771b4ab968458 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ignacy=20Kuchci=C5=84ski?= Date: Mon, 18 Aug 2025 11:44:42 +0200 Subject: [PATCH] parentalControlsManager: Add support for session limits Add ability to check if session limits are enabled for users using API introduced in malcontent 0.14.0. The `get_session_limits_async` function is actually available since 0.5.0, but the signal `session-limits-changed` was only introduced in 0.14.0, so check for function `get_daily_limit` which was introduced in 0.14.0 to be sure we're using correct version. This allows us to keep filtering apps, even if the library version doesn't fully support session limits. Will be used in the future to integrate parental controls session limits. Part-of: --- js/misc/parentalControlsManager.js | 68 ++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/js/misc/parentalControlsManager.js b/js/misc/parentalControlsManager.js index 3dfe13d5a..f4b284120 100644 --- a/js/misc/parentalControlsManager.js +++ b/js/misc/parentalControlsManager.js @@ -32,8 +32,13 @@ let Malcontent = null; if (HAVE_MALCONTENT) { ({default: Malcontent} = await import('gi://Malcontent?version=0')); Gio._promisify(Malcontent.Manager.prototype, 'get_app_filter_async'); + Gio._promisify(Malcontent.Manager.prototype, 'get_session_limits_async'); } +// We require libmalcontent ≥ 0.14.0 for session limits +const HAVE_MALCONTENT_0_14 = Malcontent && + GObject.signal_lookup('session-limits-changed', Malcontent.Manager) > 0; + let _singleton = null; /** @@ -53,6 +58,7 @@ export function getDefault() { const ParentalControlsManager = GObject.registerClass({ Signals: { 'app-filter-changed': {}, + 'session-limits-changed': {}, }, }, class ParentalControlsManager extends GObject.Object { _init() { @@ -61,6 +67,7 @@ const ParentalControlsManager = GObject.registerClass({ this._initialized = false; this._disabled = false; this._appFilter = null; + this._sessionLimits = null; this._initializeManager(); } @@ -70,6 +77,7 @@ const ParentalControlsManager = GObject.registerClass({ console.debug('Skipping parental controls support, malcontent not found'); this._initialized = true; this.emit('app-filter-changed'); + this.emit('session-limits-changed'); return; } @@ -77,16 +85,22 @@ const ParentalControlsManager = GObject.registerClass({ const connection = await Gio.DBus.get(Gio.BusType.SYSTEM, null); this._manager = new Malcontent.Manager({connection}); this._appFilter = await this._getAppFilter(); + + if (HAVE_MALCONTENT_0_14) + this._sessionLimits = await this._getSessionLimits(); } catch (e) { logError(e, 'Failed to get parental controls settings'); return; } this._manager.connect('app-filter-changed', this._onAppFilterChanged.bind(this)); + if (HAVE_MALCONTENT_0_14) + this._manager.connect('session-limits-changed', this._onSessionLimitsChanged.bind(this)); // Signal initialisation is complete. this._initialized = true; this.emit('app-filter-changed'); + this.emit('session-limits-changed'); } async _getAppFilter() { @@ -123,6 +137,40 @@ const ParentalControlsManager = GObject.registerClass({ } } + async _getSessionLimits() { + let sessionLimits = null; + + try { + sessionLimits = await this._manager.get_session_limits_async( + Shell.util_get_uid(), + Malcontent.ManagerGetValueFlags.NONE, + null); + } catch (e) { + if (!e.matches(Malcontent.ManagerError, Malcontent.ManagerError.DISABLED)) + throw e; + + console.debug('Parental controls globally disabled'); + this._disabled = true; + } + + return sessionLimits; + } + + async _onSessionLimitsChanged(manager, uid) { + // Emit 'changed' signal only if session-limits are changed for currently logged-in user + const currentUid = Shell.util_get_uid(); + if (currentUid !== uid) + return; + + try { + this._sessionLimits = await this._getSessionLimits(); + this.emit('session-limits-changed'); + } catch (e) { + // Keep the old session limits + logError(e, `Failed to get new MctSessionLimits for uid ${Shell.util_get_uid()} on session-limits-changed`); + } + } + get initialized() { return this._initialized; } @@ -152,4 +200,24 @@ const ParentalControlsManager = GObject.registerClass({ return this._appFilter.is_appinfo_allowed(appInfo); } + + /** + * Check whether parental controls session limits are enabled for the account, + * and if the library supports the features required for the functionality. + * + * @returns {bool} whether session limits are supported and enabled. + */ + sessionLimitsEnabled() { + // Are latest parental controls enabled (at configure or runtime)? + if (!HAVE_MALCONTENT_0_14 || this._disabled) + return false; + + // Have we finished initialising yet? + if (!this.initialized) { + console.debug('Ignoring session limits because parental controls not yet initialised'); + return false; + } + + return this._sessionLimits.is_enabled(); + } }); -- 2.39.5